package com.sso.client.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.sso.client.utils.Constants;
import com.sso.client.utils.CookiesGetUtil;
import com.sso.client.utils.HttpUtil;
import org.apache.commons.lang3.StringUtils;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * 使用sso公共登录页面
 *
 * @author : luyifei
 * @date : 2021/1/11
 */
public class SsoWebClient {


    private String ssoServerUrl;

    public SsoWebClient(String ssoServerUrl) {
        this.ssoServerUrl = ssoServerUrl;
    }

    /**
     * 重定向到sso登录页面
     *
     * @param request
     * @param response
     */
    public void redirectLogin(HttpServletRequest request, HttpServletResponse response) throws IOException {
        StringBuilder toLoginUrl = new StringBuilder(ssoServerUrl).append(Constants.LOGIN);
        toLoginUrl.append("?service=").append(getReturnUrl(request, false));
        response.sendRedirect(toLoginUrl.toString());
    }

    /**
     * 优先验证cookie中token，不通过再验证request参数中的token
     *
     * @param request
     * @param response
     * @return
     */
    public boolean checkToken(HttpServletRequest request, HttpServletResponse response) {

        //1 验证cookie中token
        if (checkCookieToken(request, response)) {
            return true;
        } else {
            //2 验证参数中token
            return checkParamToken(request, response);
        }
    }

    /**
     * controller层调用
     *
     * @param request
     * @param response
     */
    public String logout(HttpServletRequest request, HttpServletResponse response) {
        // 删除cookie中token
        Cookie cookie = new Cookie(Constants.TOKEN_COOKIE_KEY, null);
        cookie.setMaxAge(Constants.COOKIE_AGE_ZERO);
        cookie.setPath(Constants.COOKIE_PATH);
        response.addCookie(cookie);

        // 重定向到sso登录页面，returnUrl为当前应用域名
        StringBuilder logout = new StringBuilder(ssoServerUrl).append(Constants.LOGOUT);
        logout.append("?service=").append(getReturnUrl(request, true));
        return logout.toString();
    }

    /**
     * 校验cookie中token
     *
     * @param request
     * @param response
     * @return
     */
    private boolean checkCookieToken(HttpServletRequest request, HttpServletResponse response) {
        String token = CookiesGetUtil.getCookies(Constants.TOKEN_KEY, request);
        if (StringUtils.isEmpty(token)) {
            return false;
        }
        if (verifyToken(token)) {
            return true;
        } else {
            //cookie中token不能通过验证，删除其token
            Cookie cookie = new Cookie(Constants.TOKEN_KEY, null);
            cookie.setMaxAge(0);
            cookie.setPath(Constants.COOKIE_PATH);
            response.addCookie(cookie);
            return false;
        }

    }

    /**
     * 校验request参数中token
     *
     * @param request
     * @param response
     * @return
     */
    private boolean checkParamToken(HttpServletRequest request, HttpServletResponse response) {

        String token = request.getParameter(Constants.TOKEN_KEY);
        if (!StringUtils.isEmpty(token)) {
            //验证request参数中token合法，将token保存到cookie中
            if (verifyToken(token)) {
                Cookie cookie = new Cookie(Constants.TOKEN_KEY, token);
                cookie.setMaxAge(Constants.COOKIE_AGE_NEGATIVE);
                cookie.setPath(Constants.COOKIE_PATH);
                response.addCookie(cookie);
                return true;
            }
        }
        return false;
    }

    private boolean verifyToken(String token) {
        StringBuilder toVerifyTokenUrl = new StringBuilder(ssoServerUrl).append(Constants.VERIFY_TOKEN);
        Map<String, String> params = new HashMap<String, String>(16);
        params.put(Constants.TOKEN_KEY, token);
        try {
            String result = HttpUtil.send(toVerifyTokenUrl.toString(), params, Constants.UTF_8);
            JSONObject obj = JSON.parseObject(result);
            if (Constants.SUCCESS.equals(obj.getString(Constants.CODE_KEY))) {
                return true;
            } else {
                return false;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    private String getReturnUrl(HttpServletRequest request, boolean isLogout) {
        String url = request.getScheme() + "://";
        url += request.getHeader("host");
        if (!isLogout) {
            url += request.getRequestURI();
        }
        if (request.getQueryString() != null) {
            //判断请求参数是否为空
            url += "?" + request.getQueryString();
        }
        //TODO 排除网关或者nginx代理
        return url;
    }
}
